import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.util.*;
import java.sql.*;
import javax.swing.*;

/**
 * A JPanel for authorizing access.
 *
 * @author Jacel Evasco
 * @author Rafael Carino
 * @author Christian Paul Rosquita
 * @author Roselle Nympha Lim
 * @author Iris Reynald Quiming
 * @version 1.0
 */
public class ProfileAuthenticator extends JPanel {

    private JPanel labels = new JPanel();
    private JPanel fields = new JPanel();
    private JPanel buttons = new JPanel();
    private JPanel labelsAndFields = new JPanel();
    private JTextField iD = new JTextField();
    private JPasswordField pin = new JPasswordField();
    private JButton okay = new JButton("okay");
    private JButton clear = new JButton("clear");
    private JLabel[] fieldLabels = {
        new JLabel("ID number", SwingConstants.RIGHT),
        new JLabel("PIN", SwingConstants.RIGHT) };
    Connection connection = null;
    ResultSet resultSet = null;
    PreparedStatement preparedStatement = null;

    public ProfileAuthenticator() {
        cleanUp();
        assemble();
        configure();
        design();
        setTriggers();
        prepareConnection();
    }// end of ProfileAuthenticator()

    private void prepareConnection() {
        try {
            connection = DatabaseUtility.prepareConnection();
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        }
    } // end of prepareConnection method

    private void assemble() {
        // labels
        labels.setLayout(new BoxLayout(labels, BoxLayout.Y_AXIS));
        labels.add(fieldLabels[0]);
        labels.add(Box.createRigidArea(new Dimension(0, 15)));
        labels.add(fieldLabels[1]);
        // fields
        fields.setLayout(new BoxLayout(fields, BoxLayout.Y_AXIS));
        fields.add(iD);
        fields.add(Box.createRigidArea(new Dimension(0, 15)));
        fields.add(pin);
        // fields and labels
        labelsAndFields.setLayout(new BoxLayout(labelsAndFields,
            BoxLayout.X_AXIS));
        labelsAndFields
            .add(Box.createRigidArea(new Dimension(33, 0)));
        labelsAndFields.add(labels);
        labelsAndFields
            .add(Box.createRigidArea(new Dimension(30, 0)));
        labelsAndFields.add(fields);
        // buttons
        buttons.setLayout(new BoxLayout(buttons, BoxLayout.X_AXIS));
        buttons.add(Box.createRigidArea(new Dimension(173, 0)));
        buttons.add(clear);
        buttons.add(Box.createRigidArea(new Dimension(16, 0)));
        buttons.add(okay);
        // this
        this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
        this.add(Box.createRigidArea(new Dimension(0, 67)));
        this.add(labelsAndFields);
        this.add(Box.createRigidArea(new Dimension(0, 25)));
        this.add(buttons);

    }// end of assemble()

    private void configure() {

    }// end of configure()

    private void design() {
        // sizes
        okay.setPreferredSize(new Dimension(100, 28));
        okay.setMinimumSize(new Dimension(100, 28));
        okay.setMaximumSize(new Dimension(100, 28));
        clear.setPreferredSize(new Dimension(100, 28));
        clear.setMinimumSize(new Dimension(100, 28));
        clear.setMaximumSize(new Dimension(100, 28));
        fieldLabels[0].setPreferredSize(new Dimension(110, 28));
        fieldLabels[0].setMinimumSize(new Dimension(110, 28));
        fieldLabels[0].setMaximumSize(new Dimension(110, 28));
        fieldLabels[1].setPreferredSize(new Dimension(110, 28));
        fieldLabels[1].setMinimumSize(new Dimension(110, 28));
        fieldLabels[1].setMaximumSize(new Dimension(110, 28));
        iD.setPreferredSize(new Dimension(287, 28));
        iD.setMinimumSize(new Dimension(287, 28));
        iD.setMaximumSize(new Dimension(287, 28));
        pin.setPreferredSize(new Dimension(287, 28));
        pin.setMinimumSize(new Dimension(287, 28));
        pin.setMaximumSize(new Dimension(287, 28));
        labelsAndFields.setPreferredSize(new Dimension(500, 71));
        labelsAndFields.setMinimumSize(new Dimension(500, 71));
        labelsAndFields.setMaximumSize(new Dimension(500, 71));
        buttons.setPreferredSize(new Dimension(500, 28));
        buttons.setMinimumSize(new Dimension(500, 28));
        buttons.setMaximumSize(new Dimension(500, 28));
        this.setPreferredSize(new Dimension(500, 284));
        this.setMinimumSize(new Dimension(500, 284));
        this.setMaximumSize(new Dimension(500, 284));
        // font styles
        Font font = new Font("Segoe UI Light", Font.PLAIN, 16);
        Font labelFont = new Font("Segoe UI", Font.BOLD, 14);
        Font buttonFont = new Font("Segoe UI", Font.BOLD, 14);
        iD.setFont(font);
        pin.setFont(font);
        okay.setFont(buttonFont);
        clear.setFont(buttonFont);
        fieldLabels[0].setFont(labelFont);
        fieldLabels[1].setFont(labelFont);
        // borders
        iD.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        pin.setBorder(BorderFactory.createLineBorder(Color.BLACK, 1));
        // backgrounds
        labels.setOpaque(false);
        fields.setOpaque(false);
        buttons.setOpaque(false);
        labelsAndFields.setOpaque(false);
        // buttons
        okay.setContentAreaFilled(false);
        clear.setContentAreaFilled(false);

    }// end of design()

    private void setTriggers() {
        ActionListener actionTrigger = new ActionListener() {
            public void actionPerformed(ActionEvent anActionEvent) {
                if (anActionEvent.getSource() == okay) {
                    verifyLogin();
                    Explorer.getInstance().fetchID();
                    // clear data in the fields
                } else if (anActionEvent.getSource() == clear) {
                    iD.setText("");
                    pin.setText("");
                }
            }
        }; // end of viewerTrigger
        okay.addActionListener(actionTrigger);
        clear.addActionListener(actionTrigger);
    }// end of setTriggers

    private void verifyLogin() {
        // checks whether there is another user who is logged in
        String verifyUserLogin = "SELECT * FROM requirementstrackerschema.student"
            + " WHERE isLoggedIn = '1'";
        try {
            preparedStatement = connection
                .prepareStatement(verifyUserLogin);

            resultSet = preparedStatement.executeQuery();
            // if return not null, then there is another user who is logged in
            if (resultSet.next()) {
                JOptionPane.showMessageDialog(null, "Login failed");
            } else { // no user is logged in yet, proceed to next step...
                verifyInput();
            } // end of if-else
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        } // end of try-catch
    } // end of verifyLogin method

    private void verifyInput() {
        // query that checks if the studentID and pin is valid
        String verifyInput = "SELECT * FROM requirementstrackerschema.student"
            + " WHERE studentID = ? AND pin = ?";

        try {
            preparedStatement = connection
                .prepareStatement(verifyInput);
            preparedStatement.setString(1, iD.getText());
            preparedStatement.setString(2, pin.getText());

            resultSet = preparedStatement.executeQuery();
            // if return not null, then input is valid
            if (resultSet.next()) {
                updateStatus();
            } else { // if not valid...
                JOptionPane.showMessageDialog(null,
                    "Invalid ID number or pin");
            }
        } catch (Exception e) {
            JOptionPane.showMessageDialog(null, e);
        } // end of try-catch
    } // end of verifyInput method

    private void updateStatus() {
        // change isLoggedIn to true in the database
        String updateStatus = "UPDATE requirementstrackerschema.student"
            + " SET isLoggedIn = '1' WHERE studentID = ?";

        try {
            preparedStatement = connection
                .prepareStatement(updateStatus);
            preparedStatement.setString(1, iD.getText());
            preparedStatement.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        } // end of try-catch

        try {
            Explorer.getInstance().fetchID();
            Explorer.getInstance().getProfileMenu()
                .getProfilePeeker().fetchID();
            Explorer.getInstance().getProfileMenu()
                .getProfileEditor().fetchID();
            Explorer.getInstance().getRequirementsViewer().getData()
                .refresh();
            Explorer.getInstance().getGoalsViewer().getData()
                .refresh();
            Explorer.getInstance().getProfileMenu().getEdit()
                .setEnabled(true);
            Explorer.getInstance().getProfileMenu().getEdit()
                .setVisible(true);
            Explorer.getInstance().getGoalsViewer().isDataEmpty();
            Explorer.getInstance().getRequirementsViewer()
                .isDataEmpty();
            Explorer.getInstance().getProfileMenu().loginOrLogout();
        } catch (Exception noise) {
        }
        // show profilePeeker
        ((CardLayout) (ProfileMenu.getCards().getLayout())).show(
            ProfileMenu.getCards(), "profilePeeker");

    } // end of updateStatus method

    public void cleanUp() {
        pin.setText("");
    } // end of cleanUp
} // end of ProfileAuthenticator